;; Complete test for set! special form

;; Test 1: Basic variable definition and modification
(define x 10)
(display "Test 1 - Basic set!")
(display "\n")
(display "x before set!: ")
(display x)
(display "\n")

(set! x 20)
(display "x after set!: ")
(display x)
(display "\n\n")

;; Test 2: Function definition and using set! inside functions
(display "Test 2 - Function with set!")
(display "\n")
(define counter 0)

(define (increment)  
  (set! counter (+ counter 1))
  counter
)

(display "counter before increment: ")
(display counter)
(display "\n")

(increment)
(display "counter after first increment: ")
(display counter)
(display "\n")

(increment)
(display "counter after second increment: ")
(display counter)
(display "\n\n")

;; Test 3: Modifying a function with set!
(display "Test 3 - Modify function with set!")
(display "\n")
(define (square x) (* x x))
(display "square of 5: ")
(display (square 5))
(display "\n")

(set! square (lambda (x) (* x x x)))
(display "new square (now cube) of 5: ")
(display (square 5))
(display "\n\n")

;; Test 4: Nested scopes with set!
(display "Test 4 - Nested scopes with set!")
(display "\n")
(define outer 100)

(define (outer-func)  
  (define inner 200)
  (display "outer in outer-func: ")
  (display outer)
  (display "\n")
  (display "inner in outer-func: ")
  (display inner)
  (display "\n")
  (set! outer (+ outer 10))
  (set! inner (+ inner 20))
  (display "outer after set! in outer-func: ")
  (display outer)
  (display "\n")
  (display "inner after set! in outer-func: ")
  (display inner)
  (display "\n")
  (define (inner-func)  
    (display "outer in inner-func: ")
    (display outer)
    (display "\n")
    (display "inner in inner-func: ")
    (display inner)
    (display "\n")
    (set! outer (+ outer 5))
    (set! inner (+ inner 10))
    (display "outer after set! in inner-func: ")
    (display outer)
    (display "\n")
    (display "inner after set! in inner-func: ")
    (display inner)
    (display "\n")
  )
  (inner-func)
)

(outer-func)
(display "outer after outer-func: ")
(display outer)
(display "\n\n")

(display "All set! tests completed successfully!")
(display "\n")